#include "myscene.h"

#include <QGraphicsPixmapItem>
#include <QRandomGenerator>
#include <QSettings>
#include <QtAlgorithms>
#include <QNetworkInterface>
#include <QJsonObject>
#include <QJsonArray>
#include <QJsonDocument>

#include "configmanager.h"

MyScene::MyScene(UserInfoDialog* dialog) {
    this->dialog = dialog;
    // dialog->show();
    // 获取自己的ip
    const auto list = QNetworkInterface::allInterfaces();
    for (const QNetworkInterface &interface : list) {  // 遍历每一个网络接口
        // 获取IP地址条目列表，每个条目包含一个IP地址、子网掩码和广播地址
        const auto entryList = interface.addressEntries();
        for (const QNetworkAddressEntry &entry : entryList) { // 遍历每一个IP地址条目
            QHostAddress ip = entry.ip();
            QString ipStr = ip.toString();
            if(ip.protocol() == QAbstractSocket::IPv4Protocol && ipStr != "127.0.0.1"){
                if(ipStr.startsWith("192.168.0.") || ipStr.startsWith("192.168.1.")){
                    localIp = ipStr;
                }
            }

        }
    }

    this->order = -1; //表示还未确定顺序

    udpSocket = new QUdpSocket(this);
    port = 6666;
    connect(udpSocket, &QUdpSocket::readyRead, this, &MyScene::onUdpReadyRead);
    udpSocket->bind(QHostAddress::AnyIPv4, port);

    // 使用组播
    groupAddress.setAddress("239.2.2.222");
    udpSocket->joinMulticastGroup(groupAddress); // 绑定端口必须在加入组播之前

    ConfigManager& cm = ConfigManager::instance();

    // 发送刚进来的消息确认顺序
    QJsonObject sendObj;
    sendObj.insert("ip", this->localIp);
    sendObj.insert("operation", "进入游戏");
    sendObj.insert("avatar", cm.avatarNum);
    sendObj.insert("name", cm.nickName);
    udpSend(sendObj);

    this->init();

    // 绘制自己的头像昵称，获取举手
    hand[0] = drawAvatarAndName(cm.avatarNum, QPointF(-cm.screenWidth*3/8, cm.screenHeight*37/135), cm.nickName);

    // 两个对手的剩余牌数
    // lastItem1 = new QGraphicsTextItem();
    // QFont font;
    // font.setPixelSize(20);
    // font.setBold(true);
    // lastItem1->setFont(font);
    // lastItem1->setPlainText(QString("%1").arg(17));
    // lastItem1->setPos(player1->x() + (player1->boundingRect().width() - lastItem1->boundingRect().width())/2,
    //                   cm.screenWidth/12-cm.screenHeight/4);
    // this->addItem(lastItem1);

    // 出牌按钮和取消按钮
    // int disToCen = cm.screenWidth / 80; //边缘距离中心距离15
    // int disToCard = cm.screenHeight / 22.5; // 与下方卡牌距离30
    // int width = qRound(cm.screenWidth / 12.766); // 按钮宽度94
    // int height = cm.screenHeight / 15; // 按钮高度45

    // outCardBtn = new MyButtonItem(":/Sprites/operation/outCard.png", QSize(width, height));
    // passBtn = new MyButtonItem(":/Sprites/operation/pass.png", QSize(width, height));
    // outCardBtn->setPos(-width-disToCen, cm.myCardY-height-disToCard);
    // passBtn->setPos(disToCen, cm.myCardY-height-disToCard);
    // this->addItem(outCardBtn);
    // this->addItem(passBtn);

    QFont font;
    waitInfo = new QGraphicsTextItem("请等待其他玩家加入...");
    font.setPixelSize(40);
    font.setBold(true);
    waitInfo->setFont(font);
    waitInfo->setPos(-waitInfo->boundingRect().width()/2, -waitInfo->boundingRect().height()/2);
    this->addItem(waitInfo);

    // 开始游戏按钮
    startBtn = new QGraphicsPixmapItem(QPixmap(":/Sprites/operation/start.png").scaledToWidth(cm.screenWidth/6));
    startBtn->setPos(-startBtn->boundingRect().width()/2, cm.screenHeight/4);
}

void MyScene::mousePressEvent(QGraphicsSceneMouseEvent *event)
{
    // qDebug() << event->scenePos();
    if(!isPressed){ //保证是第一次进来, 按下滑动开始
        QPointF startPos = event->scenePos();
        QGraphicsItem* item = this->itemAt(startPos, QTransform());
        QVector<CardItem*>& myCards = gameProcess.myCards;
        ConfigManager& cm = ConfigManager::instance();
        if(item == nullptr){
            // 点击空白处取消选牌
            cancelSelectCard();
            return;
        }else if(item == outCardBtn){
            QVector<CardItem*> outCardList;
            for(int i=0; i<myCards.size();){
                if(myCards[i]->getSelectStatus()){
                    // qDebug() << myCards[i]->getCard().cardNo<<" ";
                    outCardList.push_back(myCards[i]);
                    // 从myCards中移除
                    myCards.remove(i);
                }else{
                    i++;
                }
            }
            // 选中的牌移动到屏幕中央
            // for(int i=0; i<outCardList.size()/2; i++){
            //     outCardList[i]->setPos(cm.calcu_x(outCardList.size())+i*cm.cardSpacing, outCardBtn->y()-cm.cardHeight-10);
            // }

            // 左边的玩家出牌 -cm.screenWidth*11/24, -225      cm.screenWidth/12
            // for(int i=outCardList.size()/2; i<outCardList.size(); i++){
            //     outCardList[i]->setPos(-cm.screenWidth*43/120 + i*cm.cardSpacing*2/3, -cm.screenHeight/4);
            // }

            // 右边玩家出牌
            // int cardOfRight = outCardList.size();
            // for(int i=0; i<outCardList.size(); i++){
            //     outCardList[i]->setPos(cm.screenWidth*43/120 + (i-cardOfRight+1)*cm.cardSpacing*2/3 - cm.cardWidth, -cm.screenHeight/4);
            // }

            // 重绘myCards
            for(int i=0; i<myCards.size(); i++){
                myCards[i]->setPos(cm.calcu_x(myCards.size())+i*cm.cardSpacing, cm.myCardY);
            }
            return;
        }else if(item == passBtn){
            qDebug() << "不出";
            this->cancelSelectCard();
            return;
        }else if(item == startBtn){ // 按下开始游戏按钮
            static bool isPressed = false;
            if(!isPressed){ //防止重复点击开始
                QJsonObject obj;
                obj.insert("operation", "准备");
                obj.insert("order", this->order);
                udpSend(obj);
                isPressed = true;
            }
        }

        startIndex = cm.calcu_index(myCards.size(), startPos);
        lastIndex = startIndex;
        // qDebug() << "startIndex: " << startIndex;
        if(startIndex != -1){ //正在选择牌
            isSelectingCard = true;
            gameProcess.myCards[startIndex]->drawGrayMask = true;
            gameProcess.myCards[startIndex]->update();

        }

        isPressed = true;

        //QGraphicsScene::mousePressEvent(event); // 将点击事件向下传递到item中
    }

    // CardItem* item = (CardItem*)this->itemAt(event->scenePos(), QTransform());
    // if(item != nullptr){
    //     qDebug() << "翻转" << item;
    //     item->flip();
    //     // item->changeSelectStatus();
    // }
    // qDebug() << item;

}

void MyScene::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
{
    QPointF pos = event->scenePos();
    if(isSelectingCard){
        QVector<CardItem*>& myCards = gameProcess.myCards;
        int index = ConfigManager::instance().calcu_index(myCards.size(), pos);
        if(index == -1){
            // 取消选中的牌
            cancelSelectCard();
            return;
        }
        if(!myCards[index]->drawGrayMask){
            myCards[index]->drawGrayMask = true;
            myCards[index]->update();
        }
        // 如果与最初方向反向移动则取消上一张牌的遮罩
        if((index >= startIndex && index < lastIndex) ||
            (index <= startIndex && index > lastIndex )){
            myCards[lastIndex]->drawGrayMask = false;
            myCards[lastIndex]->update();
        }
        lastIndex = index;
    }
}

void MyScene::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
{
    isPressed = false;
    if(isSelectingCard){
        isSelectingCard = false;
        QPointF endPos = event->scenePos();
        QVector<CardItem*>& myCards = gameProcess.myCards;
        int endIndex = ConfigManager::instance().calcu_index(myCards.size(), endPos);
        // 处理反向选择的情况
        if(endIndex < startIndex) std::swap(startIndex, endIndex);
        for(int i=startIndex; i<=endIndex; i++){
            myCards[i]->drawGrayMask = false;
            myCards[i]->changeSelectStatus();
        }
    }
}

void MyScene::cancelSelectCard()
{
    QVector<CardItem*>& myCards = gameProcess.myCards;
    isSelectingCard = false;
    for(int i=0; i<myCards.size(); i++){
        myCards[i]->drawGrayMask = false;
        if(myCards[i]->getSelectStatus())
            myCards[i]->changeSelectStatus();
        myCards[i]->update();
    }
}

void MyScene::udpSend(const QJsonObject &sendObj)
{
    QString sendMsg = QJsonDocument(sendObj).toJson();
    QByteArray data = sendMsg.toUtf8();
    udpSocket->writeDatagram(data.data(), data.size(), groupAddress, port);
}

void MyScene::udpSingleSend(const QJsonObject &sendObj, QString ip)
{
    QString sendMsg = QJsonDocument(sendObj).toJson();
    QByteArray data = sendMsg.toUtf8();
    udpSocket->writeDatagram(data.data(), data.size(), QHostAddress(ip), port);
}

void MyScene::init()
{
    isActive = false;
}

QGraphicsPixmapItem* MyScene::drawAvatarAndName(int avatarNum, QPointF pos, QString name)
{
    QPixmap pixmap(QString(":/Sprites/Characters/char_%1.png").arg(avatarNum)); // 创建 QPixmap 对象并缩放
    ConfigManager& cm = ConfigManager::instance();
    QGraphicsPixmapItem * item = new QGraphicsPixmapItem(pixmap.scaledToWidth(cm.screenWidth/12));
    item->setPos(pos);
    this->addItem(item);
    // 自己的昵称
    QGraphicsTextItem * myName = new QGraphicsTextItem(name);
    QFont font;
    font.setPixelSize(20);
    font.setBold(false);
    myName->setFont(font);
    QRectF meRect = item->boundingRect();
    QRectF myNameRect = myName->boundingRect();
    myName->setPos(item->x()+(meRect.width()-myNameRect.width())/2, item->y()+meRect.height());
    this->addItem(myName);

    // 举手图片
    QGraphicsPixmapItem* pixItem = new QGraphicsPixmapItem(QPixmap(":/Sprites/operation/hand.png").scaledToWidth(cm.screenWidth/40));
    pixItem->setPos(item->x()+item->boundingRect().width(), item->y() +
        (item->boundingRect().height()-pixItem->boundingRect().height())/2);
    return pixItem;
}

void MyScene::onUdpReadyRead()
{
    QByteArray buffer;
    buffer.resize(udpSocket->pendingDatagramSize());
    udpSocket->readDatagram(buffer.data(), buffer.size());
    QJsonDocument doc = QJsonDocument::fromJson(buffer);
    QJsonObject recvObj = doc.object();
    QString opt = recvObj.value("operation").toString();
    ConfigManager& cm = ConfigManager::instance();
    if(opt == "进入游戏"){
        // 玩家进入时绘制头像
        QString recvIp = recvObj.value("ip").toString();
        if(recvIp != localIp){ // 别人发的
            if(this->order == -1){ //可以确定自己是第一位并且可以告知对方是第二位
                this->order = 0;

                // 绘制右上
                hand[1] = drawAvatarAndName(recvObj.value("avatar").toInt(),
                    QPointF(cm.screenWidth*11/24 - cm.screenWidth/12, -cm.screenHeight/4), recvObj.value("name").toString());

                QJsonObject obj;
                obj.insert("operation", "确认消息");
                obj.insert("sender_order", this->order);
                obj.insert("order", 1); //告知对方为2号
                obj.insert("avatar", cm.avatarNum);
                obj.insert("name", cm.nickName);
                udpSingleSend(obj, recvIp);
            }else if(this->order == 0){
                // 绘制左上
                hand[2] = drawAvatarAndName(recvObj.value("avatar").toInt(),
                    QPointF(-cm.screenWidth*11/24, -cm.screenHeight/4), recvObj.value("name").toString());

                QJsonObject obj;
                obj.insert("operation", "确认消息");
                obj.insert("sender_order", this->order);
                obj.insert("order", 2); //告知对方为3号
                obj.insert("avatar", cm.avatarNum);
                obj.insert("name", cm.nickName);
                udpSingleSend(obj, recvIp);
            }else if(this->order == 1){
                // 绘制右上
                hand[1] = drawAvatarAndName(recvObj.value("avatar").toInt(),
                    QPointF(cm.screenWidth*11/24 - cm.screenWidth/12, -cm.screenHeight/4), recvObj.value("name").toString());

                QJsonObject obj;
                obj.insert("operation", "确认消息");
                obj.insert("sender_order", this->order);
                obj.insert("order", 2); //告知对方为3号
                obj.insert("avatar", cm.avatarNum);
                obj.insert("name", cm.nickName);
                udpSingleSend(obj, recvIp);
            }

        }

    }else if(opt == "确认消息"){
        this->order = recvObj.value("order").toInt();
        if(order == 1){ // 自己是2号
            // 绘制左上
            hand[2] = drawAvatarAndName(recvObj.value("avatar").toInt(),
                QPointF(-cm.screenWidth*11/24, -cm.screenHeight/4), recvObj.value("name").toString());
        }else if(order == 2){ // 自己是3号
            // 绘制左上(2号)
            if(recvObj.value("sender_order") == 1){
                hand[2] = drawAvatarAndName(recvObj.value("avatar").toInt(),
                    QPointF(-cm.screenWidth*11/24, -cm.screenHeight/4), recvObj.value("name").toString());
            }
            // 绘制右上(1号)
            if(recvObj.value("sender_order") == 0){
                hand[1] = drawAvatarAndName(recvObj.value("avatar").toInt(),
                    QPointF(cm.screenWidth*11/24 - cm.screenWidth/12, -cm.screenHeight/4), recvObj.value("name").toString());
            }
            // 通知玩家到齐
            QJsonObject obj;
            obj.insert("operation", "玩家到齐");
            udpSend(obj);
        }
    }else if(opt == "玩家到齐"){
        this->removeItem(waitInfo);
        this->addItem(startBtn);
    }else if(opt == "准备"){
        int targetOrder = recvObj.value("order").toInt();
        if(targetOrder == this->order){
            this->addItem(hand[0]); //自己举手

            // 如果自己是最后一个举手的，游戏开始
            QList<QGraphicsItem*> items = this->items();
            if(items.contains(hand[1]) && items.contains(hand[2])){
                // 给每位玩家发牌
                QJsonArray arr[3];
                for(int i=0; i<17; i++){
                    for(int j=0; j<3; j++){
                        arr[j].append(gameProcess.getOneRandomCard().toString());
                    }
                }
                QJsonArray diCard; // 3张底牌
                for(int i=0; i<3; i++){
                    diCard.append(gameProcess.getOneRandomCard().toString());
                }
                QJsonObject obj;
                obj.insert("operation", "游戏开始");
                for(int i=0; i<3; i++){
                    obj.insert(QString("%1").arg(i), arr[i]);
                }
                obj.insert("3", diCard);
                udpSend(obj);
            }
        }else if(targetOrder == (this->order+1)%3){ //右上举手
            this->addItem(hand[1]);
        }else if(targetOrder == (this->order+2)%3){ //左上举手
            this->addItem(hand[2]);
        }


    }else if(opt == "游戏开始"){
        // 去掉举手图标
        for(int i=0; i<3; i++) this->removeItem(hand[i]);

        // 开始游戏按钮消失
        this->removeItem(startBtn);

        // qDebug() << recvObj << "\n";

        // 绘制发到的牌
        QJsonArray cards = recvObj.value(QString("%1").arg(this->order)).toArray();

        for(int i=0; i<17; i++){
            // 图元坐标(0, 0)是正中央
            gameProcess.myCards.append(new CardItem(
                Card::parseString(cards.at(i).toString()), QSizeF(cm.cardWidth, cm.cardHeight)));
        }

        // 对这些牌进行排序
        std::sort(gameProcess.myCards.begin(), gameProcess.myCards.end(), gameProcess.myCmp);

        for(int i=0; i<17; i++){
            gameProcess.myCards[i]->setPos(cm.calcu_x(17)+i*cm.cardSpacing, cm.myCardY);
            this->addItem(gameProcess.myCards[i]);
        }

        // 绘制底牌的背面
        QJsonArray diCards = recvObj.value("3").toArray();

        if(order == 0){ //order为0的最先行动
            isActive = true;
        }
    }else if(opt == "出牌"){
        // 显示内容
        QString ip = recvObj.value("ip").toString();
        QString cards = recvObj.value("cards").toString();
        // ui->textEdit->append(ip+": "+cards);

        int nextOrder = recvObj.value("nextOrder").toInt();
        if(nextOrder == this->order){
            isActive = true;
        }
    }else if(opt == "不出"){
        QString ip = recvObj.value("ip").toString();
        // ui->textEdit->append(ip+": 不出");

        int nextOrder = recvObj.value("nextOrder").toInt();
        if(nextOrder == this->order){
            isActive = true;
        }
    }
}
